/*
This file is part of Hikari, a library that allows developers
to use Flash in their Ogre3D applications.

Copyright (C) 2008 Adam J. Simmons

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
//Adpapted to new interface
#ifndef _FLASH_CONTAINER_H_
#define _FLASH_CONTAINER_H_

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#import "PROGID:ShockwaveFlash.ShockwaveFlash" named_guids
#include "SwfUI.h"

namespace SwfUI {
	namespace detail {

		class FlashContainer:
			public IOleInPlaceSiteWindowless, 
			public IOleClientSite,
			public IBindHost,
			public IServiceProvider
		{
		public:
			int	refCount;
			Control* control;
			IMoniker* baseMoniker;

		public:
			FlashContainer(Control* control) : refCount(0),control(control)
			{
				OLECHAR szPath[MAX_PATH];
				int cch = ::GetCurrentDirectory(ARRAYSIZE(szPath), szPath);
				// GetCurrentDirectory does not finish with \, which causes the top directory to be removed :(
				// Also, error checking is for pansies.
				szPath[cch++] = L'\\';
				szPath[cch++] = 0;
				CreateURLMonikerEx(0, szPath, &baseMoniker, URL_MK_UNIFORM);
			}	

			virtual ~FlashContainer()
			{
				baseMoniker->Release();
			}

			HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv)
			{
				*ppv = 0;

				if(riid == IID_IUnknown)
				{
					*ppv = (IUnknown*)(IOleWindow*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IOleWindow)
				{
					*ppv = (IOleWindow*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IOleInPlaceSite)
				{
					*ppv = (IOleInPlaceSite*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IOleInPlaceSiteEx)
				{
					*ppv = (IOleInPlaceSiteEx*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IOleInPlaceSiteWindowless)
				{
					*ppv = (IOleInPlaceSiteWindowless*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IOleClientSite)
				{
					*ppv = (IOleClientSite*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IBindHost)
				{
					*ppv = (IBindHost*)this;
					AddRef();
					return S_OK;
				}
				else if (riid == IID_IServiceProvider)
				{
					*ppv = (IServiceProvider*)this;
					AddRef();
					return S_OK;
				}
				else
				{
					return E_NOTIMPL;
				}
			}

			ULONG STDMETHODCALLTYPE AddRef()
			{  
				return ++refCount;
			}

			ULONG STDMETHODCALLTYPE Release()
			{  
				--refCount;

				if(!refCount)
				{
					delete this;
					return 0;
				}

				return refCount;
			}

			virtual HRESULT STDMETHODCALLTYPE SaveObject(void)
			{
				return S_OK;
			}

			virtual HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)
			{
				*ppmk = 0;
				return E_NOTIMPL;
			}

			virtual HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer ** theContainerP)
			{			
				return E_NOINTERFACE;
			}

			virtual HRESULT  STDMETHODCALLTYPE ShowObject(void)
			{
				return E_NOTIMPL;
			}

			virtual HRESULT  STDMETHODCALLTYPE OnShowWindow(BOOL)
			{
				return E_NOTIMPL;
			}

			virtual HRESULT  STDMETHODCALLTYPE RequestNewObjectLayout(void)
			{
				return E_NOTIMPL;
			}

			HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE GetWindow(HWND __RPC_FAR* theWnndow)
			{
				return E_FAIL;
			}

			HRESULT STDMETHODCALLTYPE CanInPlaceActivate(void)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnInPlaceActivate(void)
			{		
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnUIActivate(void)
			{		
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE GetWindowContext(IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame, IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc, 
				LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
			{
				RECT rect;
				rect.left = 0;
				rect.top = 0;
				rect.right = control->width;
				rect.bottom = control->height;

				*lprcPosRect = rect;
				*lprcClipRect = rect;

				*ppFrame = 0;
				QueryInterface(__uuidof(IOleInPlaceFrame), (void**)ppFrame);		
				*ppDoc = 0;

				lpFrameInfo->fMDIApp = FALSE;
				lpFrameInfo->hwndFrame = 0;
				lpFrameInfo->haccel = 0;
				lpFrameInfo->cAccelEntries = 0;

				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtant)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable)
			{		
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate(void)
			{	
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE DiscardUndoState(void)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE DeactivateAndUndo(void)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(BOOL __RPC_FAR *pfNoRedraw, DWORD dwFlags)
			{		
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL fNoRedraw)
			{		
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE RequestUIActivate(void)
			{
				return S_FALSE;
			}

			HRESULT STDMETHODCALLTYPE CanWindowlessActivate(void)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE GetCapture(void)
			{
				return S_FALSE;
			}

			HRESULT STDMETHODCALLTYPE SetCapture(BOOL fCapture)
			{
				return S_FALSE;
			}

			HRESULT STDMETHODCALLTYPE GetFocus(void)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE SetFocus(BOOL fFocus)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE GetDC(LPCRECT pRect, DWORD grfFlags, HDC __RPC_FAR *phDC)
			{		
				return E_INVALIDARG;		
			}

			HRESULT STDMETHODCALLTYPE ReleaseDC(HDC hDC)
			{
				return E_INVALIDARG;
			}

			HRESULT STDMETHODCALLTYPE InvalidateRect(LPCRECT pRect, BOOL fErase)
			{	
				if(pRect)
					control->invalidateRect(pRect->left,pRect->top,pRect->right,pRect->bottom);
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE InvalidateRgn(HRGN hRGN, BOOL fErase)
			{	
				RECT rect;
				GetRgnBox(hRGN,&rect);
				control->invalidateRect(rect.left,rect.top,rect.right,rect.bottom);
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
			{
				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE AdjustRect(LPRECT prc)
			{
				if(!prc)
					return E_INVALIDARG;

				return S_OK;
			}

			HRESULT STDMETHODCALLTYPE OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT __RPC_FAR *plResult)
			{
				return S_FALSE;
			}

			HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppv)
			{
				*ppv = 0;
				if(SUCCEEDED(QueryInterface(riid,ppv)))
					return S_OK;
				else
					return E_NOINTERFACE;
			}

			HRESULT STDMETHODCALLTYPE CreateMoniker(LPOLESTR szName, IBindCtx *pBC, IMoniker **ppmk, DWORD dwReserved)
			{
				*ppmk = 0;

				if(SUCCEEDED(CreateURLMonikerEx(baseMoniker, szName, ppmk, URL_MK_UNIFORM)))
					return S_OK;
				else
					return E_UNEXPECTED;
			}

			HRESULT STDMETHODCALLTYPE MonikerBindToObject(IMoniker *pMk, IBindCtx *pBC, IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
			{
				return pMk->BindToObject(pBC,NULL,riid,ppvObj);
			}

			HRESULT STDMETHODCALLTYPE MonikerBindToStorage(IMoniker *pMk, IBindCtx *pBC, IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
			{
				return pMk->BindToStorage(pBC,NULL,riid,ppvObj);
			}
		};
	}
}

#endif